<template>
  <a-radio-group v-if="type=='radio'" @change="onChange" :value="getValue" :disabled="disabled || readOnly">
    <a-radio v-for="(item, index) in dictOptions" :key="index" :value="item.value" v-if="item.value !== ''">{{ item.text || item.label }}
    </a-radio>
  </a-radio-group>

  <a-checkbox-group v-else-if="type=='checkbox'" @change="onChange" :value="getValue" :disabled="disabled || readOnly">
    <a-checkbox v-for="(item, index) in dictOptions" :key="index" :value="item.value" v-if="item.value !== ''">{{ item.text || item.label }}
    </a-checkbox>
  </a-checkbox-group>

  <a-select
    :showSearch="showSearch"
    optionFilterProp="children"
    :filter-option="filterOption"
    v-else-if="type=='select'"
    :value="getValue"
    @change="onChange"
    :disabled="disabled || readOnly"
    :mode="mode"
    :placeholder="placeholder"
    :allowClear="allowClear"
    :getPopupContainer="
      triggerNode => {
        return triggerNode.parentNode || document.body;
      }
    "

  >
    <a-select-option v-for="(item,index) in dictOptions" :key="index" :value="item.value" :title="item.text || item.label">
      {{ item.text || item.label}}
    </a-select-option>
  </a-select>
</template>

<script>

  import {ajaxGetDictItems, ajaxGetSqlConfigItems, ajaxGetHttpConfigItems} from '@/api/api';
  import pinyin from 'js-pinyin'

  export default {
    name: 'DictSelectTag',
    props: {
      type: String,
      dictCode: String,
      sqlCode: String,
      sqlParameterConfig: Array,
      httpConfig: Object,
      options: Array,
      disabled: Boolean,
      readOnly: Boolean,
      placeholder: String,
      value: [String, Number],
      allowClear: Boolean,
      formatExpr: String,
      showSearch: {
        type: Boolean,
        default: false
      },
      mode: String,
      dictMap: {
        type: Object,
        default: () => {
        }
      },
      linkage: String,
      linkageMap: {
        type: Object,
        default: () => {
        }
      },
      // 表单对象
      form: Object,
    },
    data() {
      return {
        dictOptions: [],
        syncNum: 0, // 防止异步
      }
    },
    computed: {
      getValue() {
        // 下拉框未初始化选项时，不要显示ID
        if(this.type === 'select' && this.dictOptions.length === 0){
          return undefined
        }

        let value = ''
        if (typeof this.value !== 'number') {
          value = this.value
        } else {
          value = this.value.toString()
        }
        if (this.type == 'checkbox' || (this.type == 'select' && this.mode == 'multiple')) {
          return value ? value.split(',') : []
        } else {
          return value || undefined
        }
      },
      linkageValue() {
        if (this.linkage && this.linkageMap) {
          const result = {}
          let hasValue = false
          this.linkage.split(",").forEach(key => {
            result[key] = this.linkageMap[key]
            if (result[key] !== undefined && result[key] !== null && result[key] !== "") {
              hasValue = true
            }
          })
          return hasValue ? result : null
        }
        return null
      },
      dictOptionsMap() {
        const result = {}
        this.dictOptions.forEach(item => {
          result[item.value] = item.text || item.label
        })
        return result
      }
    },
    created() {
      //获取字典数据
      this.initDictData();
    },
    watch: {
      dictCode: {
        handler() {
          this.initDictData()
        }
      },
      sqlCode: {
        handler() {
          this.initDictData()
        }
      },
      httpConfig: {
        handler() {
          this.initDictData()
        }
      },
      options: {
        handler() {
          this.initDictData()
        }
      },
      linkageValue: {
        handler(newValue, oldValue) {
          if (JSON.stringify(newValue || {}) === JSON.stringify(oldValue || {})) {
            return
          }
          if (!(this.options && this.options.length > 0) && !this.dictCode && this.sqlCode) {
            this.updateBySqlCode()

            if (oldValue) {
              // 清空选项
              this.$emit('input', null)
              this.$emit('change', null)
            }
          }else if (!(this.options && this.options.length > 0) && !this.dictCode && this.httpConfig && this.httpConfig.httpCode) {
            this.updateByHttpCode()

            if (oldValue) {
              // 清空选项
              this.$emit('input', null)
              this.$emit('change', null)
            }
          }
        }
      }
    },
    methods: {
      initDictData() {
        if (this.options && this.options.length > 0) {
          this.dictOptions = [...this.options]
          this.formatOptionsByExpr()
        } else if (this.dictCode) {
          if (this.dictMap && this.dictMap.hasOwnProperty(this.dictCode)) {
            this.dictOptions = this.dictMap[this.dictCode];
            this.formatOptionsByExpr()
          } else {
            //根据字典Code, 初始化字典数组
            ajaxGetDictItems(this.dictCode, null).then((res) => {
              if (res.success) {
                this.dictOptions = res.result;
                this.formatOptionsByExpr()
                if (this.dictMap) {
                  this.dictMap[this.dictCode] = res.result;
                }
              }
            })
          }
        } else if (this.sqlCode) {
          this.updateBySqlCode()
        } else if (this.httpConfig && this.httpConfig.httpCode) {
          this.updateByHttpCode()
        } else {
          this.dictOptions = [];
        }
      },
      updateBySqlCode(){
        const parameter = {}
        if (this.linkage && this.linkageValue) {
          Object.assign(parameter, this.linkageValue)
        } else if(this.linkage){
          // 如果要空值查询，需要放开这里
          this.dictOptions = []
          return;
        }

        // 入参
        if (this.sqlParameterConfig && this.sqlParameterConfig.length > 0 && this.form) {
          this.sqlParameterConfig.forEach(item => {
            let value = null;
            if (item.outKey) {
              value = this.form.getFieldValue(item.outKey)
            }
            if (!value && item.defaultValue) {
              value = item.defaultValue
            }
            if (value) {
              parameter[item.parameterKey] = value
            }
          })
        }

        this.syncNum ++
        const syncNum = this.syncNum
        ajaxGetSqlConfigItems(this.sqlCode, parameter).then((res) => {
          // 防止异步
          if(syncNum !== this.syncNum){
            return;
          }
          if (res.success) {
            this.dictOptions = res.result;
            this.formatOptionsByExpr()
          }
        })
      },
      updateByHttpCode(){
        const parameter = {}
        if (this.linkage && this.linkageValue) {
          Object.assign(parameter, this.linkageValue)
        } else if(this.linkage){
          this.dictOptions = []
          return;
        }
        this.syncNum ++
        const syncNum = this.syncNum
        parameter.httpConfig = this.httpConfig
        ajaxGetHttpConfigItems(this.httpConfig.httpCode, parameter).then((res) => {
          // 防止异步
          if(syncNum !== this.syncNum){
            return;
          }
          if (res.success) {
            this.dictOptions = res.result;
            this.formatOptionsByExpr()
          }
        })
      },
      formatOptionsByExpr() {
        if (!this.formatExpr) {
          return;
        }
        this.dictOptions = JSON.parse(JSON.stringify(this.dictOptions))
        this.dictOptions.forEach(item => {
          let value = item.text || item.label
          let key = item.value
          if (value) {
            const text = this.formatExpr.replace(/\$\{key\}/g, !key ? "" : key).replace(/\$\{value\}/g, !value ? "" : value);
            item.text = text
            item.label = text
          }
        })
      },
      onChange(e) {
        let val;
        let text;
        if (this.type == "radio") {
          val = e.target.value;
        } else if (this.type == "checkbox") {
          val = e.join(",");
        } else if (this.type == "select") {
          val = this.mode == 'multiple' ? e.join(",") : e;
          val = val === undefined ? null : val
        }
        if (val && val.length > 0) {
          text = val.split(",").map(item => this.dictOptionsMap[item]).join(",")
        }
        this.$emit('input', val);
        this.$emit('change', val, text);
      },
      filterOption(input, option) {
        let optionValue = option.componentOptions.children[0].text
        let jp = pinyin.getCamelChars(optionValue)
        if(!jp){
          jp = ''
        }
        if(optionValue.toLowerCase().indexOf(input.toLowerCase()) >= 0
          || jp.toLowerCase().indexOf(input.toLowerCase())>=0){
          return true
        }else{
          return false
        }
      },
    }
  }
</script>
